Virtualisation avec KVM, la série de tutos

par Nicolas · Publié · Mis à jour

Dans cette série d’articles, nous allons étudier un peu KVM, il parait que c’est à la mode !

Un ami m’a dit il y a quelque temps : « tu devrais tester, c’est pas mal »…

A l’occasion du projet de nouveau serveur V2020 en Debian 10, je me suis alors souvenu que j’avais ceci sur la liste des nombreuses choses à tester. Ce fut donc l’occasion de m’y mettre.

Pour faire ce que je fais avec Xen (à savoir créer une image en une commande), j’ai du rester motivé car ce n’est pas aussi « tout en un ».

J’ai donc bien défriché et vous propose un « petit tour » de KVM.

Table des matières

Virtualisation avec KVM, la série de tutos

I – La virtualisation

Installation et préparation du réseau

I – KVM

A – Installation

B – Management de KVM

II – Réseau

A – Openvswitch

B – KVM

III – Conclusion

Installation d’une VM à partir d’une ISO

I – Préparatifs

II  – KVM et le stockage

A – Vite fait sur Qcow2

B – LVM

C – Création du pool LVM dans KVM

III – La première VM

A – Installation

B – Installeur Debian

IV – Commandes Virsh

V – Détails de la VM

VI – Le p’tit truc en plus

VII – Conclusion

Réseau interne

I – Nouveau bridge

II – Ajout d’une interface à la VM

III – Réflexions

IV – Debianmano en  Routeur

V – Nouvelle VM

VI – Conclusion

VLANs

I – Explication

II – Sur l’hyperviseur

A – Modification vlan pour l’hyperviseur

B – Définition dans KVM

II – Modification des VM

A  – Debianmano, le routeur

1 – Côté hyperviseur

2 – Côté VM

B – Seconde VM

1 – Côté hyperviseur

2 – Côté VM

III – Tests

IV – Spécifier les VLANs lors de la création

V – Conclusion

VM avec Debootstrap et noyau de l’hyperviseur

I – Préparatifs

II – Debootstrap

III – Création de la VM

IV – Conclusion

Préparation d’un template pour les VMs

I – Préparation Squelette

A – Sources.list pour Apt

B – Grub

C – Fstab

D – Hostname

E – Hosts

F – Interfaces

G – Resolv.conf

II – Debootstrap

III – Préparation du template

A – Montages

B – Réglage timezone

C – Réglage Locales

D – ACPID

E – Paquets supplémentaires

F – Copie squelette

G – Démontage

H – Création de l’archive

IV – Conclusion

 

I – La virtualisation

Je ne fais pas faire un cours magistral sur la virtualisation, il y a pléthore de ressources à ce sujet sur le grand internet, mais pour résumer, on trouve deux types d’hyperviseurs :

– Type 1, ou « bare metal » : l’hyperviseur est l’OS de la machine, directement sur le hardware.

Des noms ? KVM, Xen, Vmware ESXi, Hyper-V, Xen-Server (la version « Citrix de Xen »).

– Type 2, ou « hosted » : l’hyperviseur est un logiciel qui tourne sur l’OS de la machine.

Encore des noms ? Vmware Workstation, Qemu, Virtual Box. Bref, un logiciel installé sur un OS.

 

Ceci dit, de nos jours, type I, type II, cela devient de plus en plus confus… On va voir pourquoi avec KVM, et d’ailleurs pour être plus précis, on devrait dire KVM/Qemu.

Qemu, techniquement, c’est du type II. C’est un soft qui tourne sur l’OS et qui permet d’émuler une machine. Cela permet de faire tourner par exemple, une archi ARM sur un host en X86, bref un émulateur tout à fait classique.

KVM (Kernel-based Virtual Machine), c’est un module du noyau Linux (intégré depuis la 2.6.20) qui permet de transformer Linux en hyperviseur.

C’est bien beau tout ça, mais ça interagit comment ?

Et bien avec l’aide de Libvirt, une API de virtualisation. Cette API open source peut être utilisée avec d’autres solutions de virtualisation, mais on la retrouve le plus souvent associée avec KVM/Qemu.

Elle va faire « le lien » entre tout ceci et propose également des commandes pour faciliter la manipulations des VMS (les lignes de commandes Qemu brutes sont imbitables…)

Et y’a une astuce, c’est que ce trio malicieux peut bosser comme un hyperviseur de type I si l’architecture que doit émuler Qemu est identique à l’architecture de l’hôte. Pour résumer (grossièrement), il n’émule plus les instructions processeurs, vu qu’il peut les passer directement, d’où performances accrues, etc..

Impeccable !

Ceci dit, il faut s’assurer avant que votre processeur hôte supporte bien les instructions de virtualisation.

Ceci avec la commande

# cat /proc/cpuinfo

Dans les flags, vous devez voir vmx (Intel) ou svm (AMD)

Pour voir facilement :

# egrep --color 'vmx|svm' /proc/cpuinfo

Si ils n’y sont pas, vous pourrez quand même virtualiser, mais Qemu restera de « type 2 » et les performances ne seront pas extraordinaires.

Petit truc aussi au passage :

A l’occasion d’un cat /proc/cpuinfo sur un Xen, j’ai constaté que le flag n’apparaissait pas. Inquiet sur le bon fonctionnement du proc, c’est en fait normal, il faut taper :

# cat /sys/hypervisor/properties/capabilities

Pour le voir sous la forme :

hvm-X.0-x86_32 hvm-X.0-x86_32p hvm-X.0-x86_64

Bref, voila pour la petit introduction sur KVM et les hyperviseurs en général.

J’ai fait court et concis, n’hésitez pas à poser des questions si quelque chose n’est pas clair.

Installation et préparation du réseau

 

I – KVM

A – Installation

On commence par les bases :

# apt install qemu-kvm libvirt-clients libvirt-daemon-system --no-install-recommends

Dans le cadre d’un serveur headless, le –-no-install-recommends est, justement, recommandé …

A la différence de Xen, KVM ne nécessite pas de booter sur un noyau particulier, donc rien d’autre à faire.

Pour  voir si ça tourne :

# service libvirtd status

A y est, c’est prêt… 🙂

B – Management de KVM

Pour le management des VMs, on trouve deux solutions :

Virsh, c’est un peu l’équivalent de la commande xl de Xen et ça se lance ainsi :

# virsh

On arrive alors dans la console virsh.

On peut taper par exemple :

virsh# help

Et pour quitter :

virsh# exit

Et on peut aussi passer le tout en une ligne :

# virsh node-info

Vous affiche les infos de l’host.

# virsh list

Cette commande vous affiche les VMs qui tournent.

Pour voir à la fois celles qui tournent et celles à l’arrêt, ce sera :

# virsh list --all

On reviendra de toute façon sur virsh en temps et en heure. Pour les impatients  : https://linux.die.net/man/1/virsh

 

II – Réseau

A – Openvswitch

Pour le réseau, comme à mon habitude, j’utilise Openvswitch car c’est le bien.

# apt install openvswitch-switch

Et on va ajouter le premier bridge

# ovs-vsctl add-br br0

Nous allons modifier le fichier interfaces /etc/network/interfaces de l’hyperviseur :

allow-ovs br0

 iface br0 inet static

 address IP_PUBLIQUE

 netmask 255.255.255.0

 gateway GATEWAY

 ovs_type OVSBridge

 ovs_ports eth0

allow-br0 eth0

 iface eth0 inet manual

 ovs_bridge br0

 ovs_type OVSPort

ceci afin de le brancher directement sur le br0, etc…

Si votre port est nommé autrement (avec le nouveau système de Debian), vous adaptez, bien évidement.

Un p’tit reboot (on pourrait faire sans, mais ainsi, je valide que mon fichier est sans erreurs)

# reboot

Et voila, l’hyperviseur est connecté sur le bridge br0 pour sortir, et ce bridge permettra à d’autres machines de sortir directement.

 

B – KVM

On va confier la gestion du réseau des VMs au système de pools de KVM. C’est optionnel, mais pratique.

Pour voir ce qu’il y a en place :

# virsh net-list --all

Et ce truc par défaut, on le supprime :

# virsh net-undefine default

On va maintenant lui dire de prendre en compte notre tout nouveau switch br0.

Cela se fait en le définissant dans un fichier xml, nommé, par exemple, front.xml :

<network>

<name>ovs-front</name>

<forward mode='bridge'/>

<bridge name='br0'/>

<virtualport type='openvswitch'/>

</network>

Il faut ensuite l’insérer et l’activer :

# virsh net-define front.xml

# virsh net-start ovs-front

# virsh net-autostart ovs-front

Pour voir si tout est ok :

# virsh net-list

Voila, c’est prêt !

 

III – Conclusion

KVM/Qemu est en place, le réseaux est prêt. Il ne reste plus qu’a créer nos VMS et vous allez voir que par rapport à Xen où je n’expliquais qu’une seule façon de faire (je reviendrais d’ailleurs dessus), ici, on va balayer plusieurs méthodes et comprendre ainsi un peu mieux les arcanes du boot de linux.

Et pour commencer, on va se faire une petite VM en partant d’une ISO de Debian, la méthode la plus simple

 

Installation d’une VM à partir d’une ISO

I – Préparatifs

On va commencer par télécharger l’ISO que l’on veut installer, au hasard … une Debian :

# mkdir /img

# cd /img

# wget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-10.3.0-amd64-netinst.iso

# mv debian-10.3.0-amd64-netinst.iso debian.iso

# cd

On pourrait tout à fait choisir de tester FreeBSD, CentOS, Fedora ou tout autre distribution.

 

Pour créer les VMs, on va utiliser virt-install qui s’installe de la sorte :

# apt install virtinst --no-install-recommends

 

II  – KVM et le stockage

Niveau stockage, KVM peut utiliser différents formats.

Son format à lui, c’est le qcow2, mais il gère aussi les disques virtuels venant de Vmware, le stockage en NFS, etc, … et également ce que j’affectionne : LVM.

A – Vite fait sur Qcow2

Dans mes articles, j’utilise exclusivement LVM, mais pour info, si vous voulez utiliser qcow2, il faut déjà installer ceci :

# apt install qemu-utils

Puis pour créer votre fichier image :

# qemu-img create -f qcow2 /imgvms/test1.qcow2 5G

Et ensuite, dans les commande virt-inst, vous remplacez les LVs par vos fichiers qcow2 avec par ex :

--file /imgvms/test1.qcow2

B – LVM

Comme on part sur du LVM, on va déjà devoir l’installer :

# apt install lvm2

Virsh permet de builder automatiquement PV, VG, etc.. mais je préfère le faire à la main avant.

Admettons que ce soit la partition sda2 qui va servir.

On va la marquer comme LVM (8E) avec cfdisk par ex :

# cfdisk /dev/sda

La, vous changez le type, puis écrivez les modifications.

 

Ensuite, on créé le PV et le VG :

# pvcreate /dev/sda2

# vgcreate vg0 /dev/sda2

 

C – Création du pool LVM dans KVM

Maintenant, on peut passer à la définition du VG dans virsh :

# virsh pool-define-as kvm-lvm logical --source-name vg0 --target /dev/vg0

Notez bien que le nom de mon VG dans virsh est différent de son vrai nom.

Ensuite, on active :

# virsh pool-start kvm-lvm

# virsh pool-autostart kvm-lvm

On peut lister

# virsh pool-list

Les autres pools ne gênent pas, on va les garder (le img sert pour indexer les ISOs, je n’ai pas encore eu le temps de creuser cet aspect…)

Avoir un pool de stockage défini dans KVM est tout à fait optionnel. On pourrait tout à fait s’en passer et créer les LVs à la main mais pour certaines manipulations qu’on verra plus tard (clone par exemple, c’est nécessaire, enfin, si on passe par le clonage via virsh… bref, ça ne mange pas de pain…)

 

III – La première VM

A – Installation

On peut enfin lancer la création et l’installation de notre première VM avec :

virt-install --name debianmano \

--vcpus 1 \

--cpu host \

--ram 1024 \

--location /img/debian.iso \

--disk pool=kvm-lvm,size=4,bus=virtio \

--network network:ovs-front,model=virtio,mac=52:54:00:11:11:11,target=debianmano.0 \

--graphics none \

--console pty,target_type=serial \

--extra-args='console=ttyS0' \

--os-variant debian10

Au niveau des paramètres :

Plus d’infos ici : https://linux.die.net/man/1/virt-install

WARNING MAC :

Si vous êtes sur un serveur dédié, voyez avec votre prestataire comment gérer les Macs. Chez Online par ex, il faut la générer et faire en sorte que l’interface de VM qui sort avec l’IP FO soit bien configurée avec la MAC générée au préalable.

Chez soi, on s’en « cogne, » mais on peut tout à fait donc forcer une MAC (sans, ce sera au hasard, avec cependant toujours 52:54:00 qui correspond à KVM.

 

B – Installeur Debian

Une fois lancé et passé les messages de boot, on se retrouve avec un installeur Debian classique.

Choix de langue : C, puis on définit sa localisation.
Configuration du réseau (votre VM sera donc dans le même network que l’hyperviseur, par exemple une IP publique en cas de serveur dédié ou une IP en 192.168… si vous êtes chez vous).
Pour le partitionnement, on va prendre auto mais sans LVM, et on poursuit l’installation.

A la question GRUB : on l’installe sur /dev/vda.

Il se peut qu’à la fin, la VM ne se relance pas (je n’ai pas compris pourquoi, vu que ça ne le fait pas systématiquement)

La commande  qui permet de se connecter à la console :

# virsh console debianmano

vous dira que le domaine est coupé.

Dans ce cas, pour le démarrer :

# virsh start debianmano

Et si vous voulez la console en même temps.

# virsh start debianmano --console

 

On voit Grub puis le chargement initial. Les autres messages ne s’affichent pas (configuration par défaut de Grub)

Et à un moment, on arrive sur l’invite de connexion.

Vous pouvez alors vous connecter sur votre VM et cette dernière doit communiquer correctement sur le réseau (ping, etc…)

Pour quitter la console, c’est CTRL + ] (en physique car en ssh, je dois faire CTRL ¤)

 

IV – Commandes Virsh

Au passage, une liste (non exhaustive) de commande utile :

# virsh autostart debianmano

Active le démarrage automatique de la VM.

# virsh reboot debianmano

Reboot de la machine (via ACPI)

# virsh shutdown debianmano

Shutdown de la machine (via ACPI)

# virsh destroy debianmano

Simule le coup de la prise…

# virsh suspend debianmano

# virsh resume debianmano

Met en pause et réactive la VM

# virsh edit debianmano

Permet d’éditer le fichier de conf de la VM

# virsh dumpxml debianmano > file.xml

Dump la configuration de la VM dans un fichier

# virsh define file.xml

Créer une nouvelle machine selon un fichier

# virsh create file.xml

La même chose, mais démarre en plus la machine.

# virsh undefine debianmano

Supprime la VM (mais ne l’arrête pas si elle tourne…)

Pour supprimer aussi le LV créé automatiquement :

# virsh vol-delete debianmano kvm-lvm

 

V – Détails de la VM

Bon que remarque t’on  avec cette VM ?

Contrairement aux VMs de Xen qui, si on n’utilise pas PyGrub (ou PVGRUB), utilisent le kernel/initramfs de l’hyperviseur, ici, on a une machine « complète » : Grub, chargement du noyau…

Une machine en quelque sorte plus « autonome ». Il sera ainsi possible de faire des modifications du noyau directement dans la VM.

En parlant de Grub, sur la VM, on va éditer le fichier /etc/default/grub pour y modifier les deux lignes :

GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0"

GRUB_TERMINAL="serial console"

Puis :

debianmano# update-grub

Ceci nous permettra de voir les messages du kernel au boot.

Au niveau Openvswitch :

# ovs-vsctl show

nous montre bien le port nommé debianmano.0 connecté sur le br0

Et en ce qui concerne le LV :

# virsh vol-list kvm-lvm

Qu’on peut le voir aussi avec :

# lvs

Tout est en ordre.

Et si vous voulez voir le fichier de configuration de la VM :

#virsh edit debianmano

Ho, le joli XML… (je ne suis pas fan, mais ca n’engage que moi…)

 

VI – Le p’tit truc en plus

Admettons que la VM soit coupée et que vous souhaitiez accéder à ses fichiers.

Avec Xen et mon système de VMS, le FS (ext4) est directement sur le LV, je peux donc le monter directement :

# mount /dev/vg0/monvol /mnt

Mais ici, ce n’est pas le cas. Le LV contient la(les) partitions créées pendant l’installation de la Debian.

On verra plus tard comment s’y connecter de façon « bas niveau », mais en attendant, voila un outil pratique …

Cela s’installe avec :

# apt install libguestfs-tools --no-install-recommends

On va couper la VM :

virsh shutdown debianmano

Puis :

# guestmount -d debianmano -i /mnt

La, on patiente un peu..

Et on a le FS de la VM monté dans /mnt… Tada…

Pour démonter :

# guestunmount /mnt

On peut relancer la VM, on va en avoir besoin pour la suite :

# virsh start debianmano

 

VII – Conclusion

Voila, vous savez maintenant comment créer une VM à partir d’une ISO. Simple non ?

Avant de voir l’autre façon de faire à l’aide de debootstrap, nous allons discuter réseau dans la partie suivante.

Réseau interne

Notre première VM est branchée directement sur le bridge br0 d’Openvswitch, elle est au même « niveau réseau » que l’hyperviseur.

Admettons que nous voulions aussi avoir la possibilité d’avoir des VMs sur un réseau interne, ne disposant donc pas directement d’une « sortie » via l’eth0/br0 de l’hyperviseur.

C’est ce que nous allons voir dans cet article.

I – Nouveau bridge

Tout d’abord, nous allons créer un nouveau bridge au sein d’Openvswitch.

# ovs-vsctl add-br brint

Nouveau bridge sobrement appelé brint.

 

Dans KVM, on va le définir dans un fichier back.xml :

<network>

<name>ovs-back</name>

<forward mode='bridge'/>

<bridge name='brint'/>

<virtualport type='openvswitch'/>

</network>

Puis  :

# virsh net-define back.xml

# virsh net-start ovs-back

# virsh net-autostart ovs-back

 

Sur l’hyperviseur, on va lui offrir la possibilité de communiquer sur ce bridge en passant par l’interface interne créée automatiquement.

Pour se faire :

# ip addr add 10.99.1.250 dev brint

# ip link set brint up

# ip route add 10.99.1.0/24 dev brint

II – Ajout d’une interface à la VM

Pour tester, nous allons brancher à chaud une nouvelle interface réseau à notre première VM. L’avantage de la virtualisation, car aller brancher une carte réseau sur une vrai machine qui tourne, je ne m’y risquerais pas…

Pour voir déjà l’existant :

# virsh domiflist debianmano

On lui ajoute l’interface ainsi :

# virsh attach-interface debianmano network ovs-back --model virtio --target debianmano.1 --mac 52:54:00:11:11:12 --persistent

Au passage, pour détacher, c’est :

# virsh detach-interface debianmano bridge --mac 52:54:00:11:11:12 --config

 

Si on regarde le fichier de configuration :

# virsh edit debianmano

On peut voir la section pour cette interface qui a été ajoutée :

...

<interface type='network'>

<mac address='52:54:00:11:11:12'/>

<source network='ovs-back'/>

<target dev='debianmano.1'/>

<model type='virtio'/>

<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>

</interface>

...

Puis dans la VM debianmano :

# virsh console debianmano

On va regarder la nouvelle interface ajoutée :

debianmano# ip a

Ici, c’est enp7s0 qui est ajoutée. Donc :

debianmano# ip addr add 10.99.1.1 dev enp7s0

debianmano# ip link set enp7s0 up

debianmano# ip route add 10.99.1.0/24 dev enp7s0

On teste un ping vers l’hyperviseur :

debianmano# ping 10.99.1.250

Et dans l’hyperviseur :

# ping 10.99.1.1

Ceci doit fonctionner sans encombres.

 

III – Réflexions

On va faire une petite pause pour voir comment utiliser au mieux tout cela.

Très souvent, dans le cas ou l’on a besoin d’isoler un réseau de VMs sur un hyperviseur, le plus simple est d’effectuer l’interconnexion des réseaux (externe et interne) au niveau de l’hyperviseur. Typiquement ce qui est utilisé avec les hyperviseurs de type II si on ne cherche pas à complexifier.

Ici, on pourrait le faire en autorisant le forward IP sur l’hyperviseur, plus le lien sur le bridge interne crée auparavant, les régles de NAT…

Coté VM, on les connecterait au brint, en déclarant l’adresse IP de l’hyperviseur sur ce bridge en gateway.

Ok, cela fonctionne….

…mais je n’aime pas.

Quand je virtualise, je veux que l’hyperviseur ne fasse que cela.

Pour le routage vers le réseau interne des VMS, j’utilise une VM spécifique avec un lien sur le br0 (et donc une IP « externe ») et un lien sur le brint. C’est elle qui s’occupera du forward, du nat, etc…

L’hyperviseur garde son IP « principale » uniquement pour l’administration. Et il garde aussi le contact avec les VM mais uniquement pour de la gestion.

 

IV – Debianmano en  Routeur

Ce qu’on va faire pour tester, c’est transformer notre première VM en routeur :

debianmano# echo 1 > /proc/sys/net/ipv4/ip_forward

Puis

debianmano# iptables -t nat -A POSTROUTING -s 10.99.1.0/24 -j SNAT --to 192.168.1.100

Son IP « externe » étant, vous l’aurez compris 192.168.1.100

V – Nouvelle VM

On va donc maintenant faire une machine uniquement branchée sur brint :

# virt-install --name newvm \

--vcpus 1 \

--cpu host \

--ram 1024 \

--location /img/debian-10.2.0-amd64-netinst.iso \

--disk pool=kvm-lvm,size=4,bus=virtio \

--network network:ovs-back,model=virtio,target=newvm.0 \

--graphics none \

--console pty,target_type=serial \

--extra-args='console=ttyS0' \

--os-variant debian10

On fait l’installation avec pour le réseau, une IP du genre 10.99.1.2, Gateway 10.99.1.1 (la première VM).

Une fois l’installation effectuée et la VM démarrée :

#virsh console newvm

On doit pouvoir pinguer debianmano :

newvm# ping 10.99.1.1

Également l’hyper (qui est encore présent sur le même réseau) :

newvm# ping 10.99.1.250

Par contre, la route passe bien par la premiere VM  :

newvm# ip route

renvoie :

default via 10.99.1.1 dev enp1s0 onlink

10.99.1.0/24 dev enp1s0 proto kernel scope link src 10.99.1.2

 

Depuis debianmano et l’hyperviseur, on doit également pouvoir pinguer newvm sur son IP 10.99.1.2.

 

VI – Conclusion

Le réseau interne est fonctionnel, nous avons la seconde VM qui communique avec l’extérieur par le biais de la VM routeur. L’hyperviseur ne gère en rien le routage.

C’est bien, mais pas top, car j’aime utiliser les VLANs et nous allons voir justement comment les intégrer dans l’article suivant.

VLANs

I – Explication

Je gère mes réseaux ainsi :

Une VM routeur avec une ip « externe » sur le bridge et plusieurs ips sur plusieurs réseaux internes :

Un premier réseau 10.10.1.0/24 qui est utilisé pour les communications Extérieur -> VMs (frontal web, postfix, vpn, etc…) et aussi pour les communications VMs -> extérieur (mise à jour, etc…).

Les VMs pour communiquer entres elles utilisent un réseau 10.20.1.0/24. Par exemple, frontal web vers serveurs backweb, postfix vers ldap, serveur divers vers stockage en cluster…

Bon, techniquement, j’utilise encore un autre réseau pour l’intercommunication dans les clusters, mais j’en parle déjà dans l’article sur ….

Et pour terminer, pour les communications Hyperviseur – VMs (ssh, ntp, etc..), j’utilise encore un autre réseau, le 10.99.1.0/24

Compliqué ? Oui, mais utile (facilite grandement le traitement avec Netflow, Ipfix, etc…, mais on reviendra plus tard sur cela dans une autre série d’articles.

Et pour gérer tout cela, au lieu de monter un nouveau bridge par réseau, on va simplement utiliser le principe des VLANs.

 

II – Sur l’hyperviseur

A – Modification vlan pour l’hyperviseur

Pour mémoire, nous avions brancher l’hyperviseur sur le brint à l’aide des commandes suivantes :

# ip addr add 10.99.1.250 dev brint
# ip link set brint up
# ip route add 10.99.1.0/24 dev brint

Il n’y a qu’une chose à faire, c’est indiquer le VLAN à utiliser sur le port.

Et cela se fait ainsi :

# ovs-vsctl set port brint tag=99

On peut voir

# ovs-vsctl show

indique :

...

Port brint

  tag: 99

  Interface brint

    type: internal

...

 

B – Définition dans KVM

Dans un fichier ovs-vlans.xml :

<network>

<name>ovs-vlans</name>

<forward mode='bridge'/>

<bridge name='brint'/>

<virtualport type='openvswitch'/>

<portgroup name='vlandef' default='yes'>

</portgroup>

<portgroup name='vlan99'>

<vlan>

<tag id='99'/>

</vlan>

</portgroup>

<portgroup name='vlans1020'>

<vlan trunk='yes'>

<tag id='10'/>

<tag id='20'/>

</vlan>

</portgroup>

</network>

Toujours sur le brint, mais on y ajoute la notion de portgroup.
Un qui trunk les VLANs 10 et 20 (toutes mes machines en ont besoin, autant mettre les deux sur un seul port) et un qui dessert le vlan 99.

Je garde le 99 sur une autre interface, question d’habitude et de cloisonnement.

On injecte et on démarre :

# virsh net-define ovs-vlans.xml

# virsh net-start ovs-vlans

# virsh net-autostart ovs-vlans

 

II – Modification des VM

On va modifier les VMS :

A  – Debianmano, le routeur

1 – Côté hyperviseur

On va lui attacher une nouvelle interface :

# virsh attach-interface debianmano network ovs-vlans --model virtio --target debianmano.2 --mac 52:54:00:11:11:13 --config

Ceci afin de créer automatiquement l’entrée dans le fichier de configuration, configuration qu’on modifiera juste après, la commande virsh attach-interface ne permettant pas de spécifier les portgroups.

On édite donc son fichier de configuration pour y ajouter les portgroup :

# virsh edit debianmano

Vous éditez :

...

première interface qu'on ne tripote pas...

...

<interface type='network'>

<mac address='52:54:00:11:11:12'/>

<source network='ovs-vlans' portgroup='vlans1020'/>

<target dev='debianmano.1'/>

<model type='virtio'/>

<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>

</interface>

<interface type='network'>

<mac address='52:54:00:11:11:13'/>

<source network='ovs-vlans' portgroup='vlan99'/>

<target dev='debianmano.2'/>

<model type='virtio'/>

<address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>

</interface>

Il faut ajouter les portgroup dans <source network>.
Un sur le trunk 10-20 et l’autre sur le vlan99.

On ne touche pas à la première interface.

2 – Côté VM

On retourne dans la VM :

# virsh console debianmano

On va modifier /etc/default/grub :

GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"

afin de récupérer les noms classiques (eth0, eth1, etc…)

Puis :

debianmano# update-grub

On va éditer le fichier /etc/network/interfaces :

auto eth0

 iface eth0

 address 192.168.1.100

 netmask 255.255.255.0

 gateway 192.168.1.254

 

auto eth1.10

 iface eth1.10 inet static

 address 10.10.1.1

 netmask 255.255.255.0

 

auto eth1.20

 iface eth1.20 inet static

 address 10.20.1.1

 netmask 255.255.255.0

 

auto eth2

 iface eth2 inet static

 address 10.99.1.1

 netmask 255.255.255.0

Ne reste plus qu’à arrêter la machine.

# virsh shutdwon debianmano

 

B – Seconde VM

De la même manière que pour le routeur…

1 – Côté hyperviseur

On va lui attacher une nouvelle interface :

# virsh attach-interface newvm network ovs-vlans --model virtio --target newvm.1 --mac 52:54:00:11:11:21 --config

On édite son fichier de configuration pour y ajouter les portgroup :

# virsh edit newvm

Et vous éditez :

<interface type='network'>

<mac address='52:54:00:62:ec:4c'/>

<source network='ovs-vlans' portgroup='vlans1020'/>

<target dev='newvm.0'/>

<model type='virtio'/>

<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>

</interface>

<interface type='network'>

<mac address='52:54:00:11:11:21'/>

<source network='ovs-vlans' portgroup='vlan99'/>

<target dev='newvm.1'/>

<model type='virtio'/>

<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>

</interface>

La, on change les deux interfaces. La première passe sur le ovs-vlans sur le trunk 10-20, la seconde, sur le vlan99.

 

2 – Côté VM

On retourne dans la VM :

# virsh console newvm

On va modifier /etc/default/grub :

GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"

Puis :

newvm# update-grub

On va éditer le fichier /etc/network/interfaces :

auto eth0.10

 iface eth0.10 inet static

 address 10.10.1.2

 netmask 255.255.255.0

 gateway 10.10.1.1

 

auto eth0.20

 iface eth0.20 inet static

 address 10.20.1.2

 netmask 255.255.255.0

 

auto eth1

 iface eth2 inet static

 address 10.99.1.2

 netmask 255.255.255.0

Ne reste plus qu’à arrêter la machine.

# virsh shutdwon newvm

 

III – Tests

On relance les deux VMs :

# virsh start debianmano

# virsh start newvm

Puis on va déjà regarder :

# virsh domiflist debianmano

# virsh domiflist newvm

On doit bien voir ce qu’on s’attendait à voir 😉

On peut donc supprimer l’ancienne définition de brint dans KVM :

# virsh net-destroy ovs-back

# virsh net-undefine ovs-back

 

Sur le routeur (debianmano), on va réactiver le routage :

# virsh console debianmano

Puis :

debianmano# echo 1 > /proc/sys/net/ipv4/ip_forward

debianmano# iptables -t nat -A POSTROUTING -s 10.10.1.0/24 -j SNAT --to 192.168.1.100

Et depuis newvm, on doit pouvoir pinguer le monde entier.

Rien de compliqué au final.

 

IV – Spécifier les VLANs lors de la création

Comme je l’ai expliqué, la commande virsh attach-interface ne permet pas de passer le paramètre portgroup.

Par contre, pour la création avec virt install, on peut tout à fait spécifier les portgroup de la sorte :

--network network:ovs-vlans,portgroup=vlans1020,model=virtio,mac=52:54:00:AA:BB:CC,target=newvm.1

 

 

V – Conclusion

Et voila, vous savez utilisez les VLANs avec KVM et Openvswitch. Bien évidement, libre à vous de faire plus simple, mais au moins, s’il faut faire compliqué, vous saurez 😉

Dans la partie suivante, nous allons voir la première méthode pour créer une VM à partir de debootsrap.

VM avec Debootstrap et noyau de l’hyperviseur

Dans cette cinquième partie de la série sur KVM, nous allons commencer à creuser un peu car faire des machines à partir d’une ISO, c’est rigolo, mais ce n’est pas pratique. Question automatisation, on a vu mieux.

Il est tout a fait possible de l’automatiser avec la fonction de preseed. C’est un fichier qui simule ce que vous pourriez taper au clavier. C’est mieux, mais bon, ça reste pas terrible terrible à mon gout.

On va donc tenter de faire quelque chose qui va nous rapprocher de ce que Xen permet avec xen-create-image, en utilisant debootstrap.

Debootstrap, c’est un truc tout bête qui vous permet de préparer une Debian depuis une autre Debian.

Et avec cette façon de faire, on peut encore procéder de deux façons…

La première, qu’on va voir ici et qui est similaire aux machines Xen par défaut, où une VM va utiliser le noyau de l’hyperviseur pour booter.

I – Préparatifs

On va créer le LV en passant par virsh :

# virsh vol-create-as kvm-lvm debiandeboot 4G

On peut le voir dans :

# virsh vol-list kvm-lvm

 

Ensuite, on va simplement le formater :

# mkfs.ext4 /dev/vg0/debiandeboot

Puis on le monte :

# mount /dev/vg0/debiandeboot /mnt

 

II – Debootstrap

Il suffit de l’installer :

# apt install debootstrap

Et tout simplement :

# debootstrap stable /mnt/

Bien sur, on s’assure que le point de montage soit disponible.

Ensuite, on va juste changer le mdp root de cette nouvelle Debian en chrootant :

# chroot /mnt

Puis :

chroot# passwd root

chroot# exit

Avant de lancer la création de la machine, on va désactiver une fonction qui, sinon, va nous faire un boucle pendant 30 sec.

On édite le fichier /etc/initramfs-tools/conf.d/resume pour modifier :

# RESUME=xxxxxx

RESUME=none

On termine avec :

# update-initramfs -u

On pense à démonter :

# umount /mnt

 

III – Création de la VM

On lance la création de la machine :

virt-install --name debiandeboot

--vcpus 1

--cpu host

--ram 1024

--import

--disk vol=kvm-lvm/debiandeboot,bus=virtio

--network=none

--boot kernel=/vmlinuz,initrd=/initrd.img,kernel_args="root=/dev/vda console=ttyS0"

--graphics none

--console pty,target_type=serial

--os-variant debian10

 

IV – Conclusion

Une fois la machine chargée, on peut se connecter dessus, mais, c’est tout.

Le FS est en read only (bah oui, pas de fstab), le hostname n’est pas configuré, le swap n’existe pas, pas de réseau…. il manque plein de choses, mais au moins, ça boot.

L’important ici était de vous montrer la technique.

Dans la partie suivante, nous commencerons à préparer le terrain pour créer des VMs « complètes », en préparant un template pour nos futures VMs.

Préparation d’un template pour les VMs

Dans cette sixième partie de la série sur KVM, nous allons voir la création d’un template à partir de deboostrap.

Ce template servira à la création de VM autonome, c’est à dire avec un grub, un noyau propre bref plus facilement bidouillable (c’est bien plus simple et moins risqué pour faire des modifs du noyau, etc…)

Ceci reste faisable avec la méthode précédente, en faisant du coup le travail sur des copies du noyau sur l’hyperviseur, mais ça laisse quand même un gros risque de « foirage »…

Puis la, on peut templater ce qu’on veut au final, une veille version de Debian, une sid, voir une autre distribution de Linux.

I – Préparation Squelette

Afin de faciliter le déploiement de mes VMs, j’ai un répertoire skel contenant les fichiers qui seront chargés (et modifiés pour certains) pour chaque VM à l’aide de commandes sed.

On va donc préparer tout cela.

Ici, je reste simple et ne couvre pas certains fichiers, mais libre à vous d’ajouter ceux que vous désirez.

Pour commencer, on se positionne dans le répertoire /root :

# cd

Puis :

# mkdir vm/skel/etc -p

# cd vm/skel/etc

Le répertoire /root/vm contiendra des scripts bash dont on parlera plus tard.

 

A – Sources.list pour Apt

On créé un répertoire :

# mkdir apt

On va copier le fichier sources.list depuis l’hyperviseur

# cp /etc/apt/sources.list apt/

 

B – Grub

On va créer un répertoire :

# mkdir default

# cd default

Et dedans, créez un fichier grub semblable à cela :

GRUB_DEFAULT=0

GRUB_TIMEOUT=1

GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`

GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0"

GRUB_TERMINAL="console serial"

GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1"

On règle pour visionner les messages de boot, pour avoir la console et au passage, on remet le nom des interfaces en ethX.

On revient dans /root/vm/skel/etc/ :

#cd ..

 

C – Fstab

Créez un fichier fstab avec ceci :

UUID=rootuuid / ext4 errors=remount-ro 0 1

UUID=swapuuid none swap sw 0 0

« rootuuid » et « swapuuid » seront modifiés lors de la création de notre VM.

 

D – Hostname

un fichier hostname :

debian

Ici, on modifiera « debian » en fonction de la future VM.

 

E – Hosts

Un fichiers hosts :

127.0.0.1 localhost

127.0.1.1 debian

La encore, ce sera « debian » qui sera modifié

 

F – Interfaces

Pour le réseau, création du répertoire :

# mkdir network

# cd network

Et ici, un fichier interfaces :

auto lo

 iface lo inet loopback

 

auto eth0.10

 iface eth0.10 inet static

 address 10.10.1.IP

 netmask 255.255.255.0

 gateway 10.10.1.1

 

auto eth0.20

 iface eth0.20 inet static

 address 10.20.1.IP

 netmask 255.255.255.0

 

auto eth1

 iface eth1 inet static

 address 10.99.1.IP

 netmask 255.255.255.0

Ici, c’est « IP » qui sera modifié.

Et on revient en arrière :

# cd ..

 

G – Resolv.conf

Et pour finir, un fichier resolv.conf avec votre resolveur :

nameserver 1.1.1.1

par exemple…

 

II – Debootstrap

On revient dans /root/vm :

# cd /root/vm

Et on va y créer un dossier pour le template :

# mkdir debugo

Pour le debootstrap, une petite astuce pour aller plus vite en utilisant l’iso :

# mount -o loop /img/debian.iso /media/cdrom/

Et on lance :

# debootstrap --no-check-gpg --include=grub-pc,linux-image-amd64,locales \

--exclude=os-prober stable debugo file:/media/cdrom

Je rajoute les paquets pour grub et le noyau et j’exclue au passage os-prober qui nous ferait apparaitre l’OS de l’hyperviseur dans le Grub de la VM…

III – Préparation du template

On va préparer le template en quelques étapes.

A – Montages

# mount -t sysfs /sys debugo/sys

# mount -t proc /proc debugo/proc

# mount --bind /dev debugo/dev

# mount -t devpts /dev/pts debugo/dev/pts

# mount --bind /tmp debugo/tmp

Puis :

cp /etc/apt/sources.list debugo/etc/apt/

Pourquoi je copie le sources.list à ce moment ?

Pour la suite, les apt dans le chroot nécessitent un sources.list, qui n’est pas présent par défaut.

Et je ne copie que celui ci car durant la création du template je peux rajouter des paquets qui modifient des fichiers que j’ai déjà configuré (par ex, postfix), la copie du squelette ne doit donc intervenir qu’à la fin.

 

Maintenant, chrootons :

# LANG=C chroot /mnt

Et pour être sur (au cas ou votre iso ne serait pas à jour par exemple et que vous ne l’ayez pas vu) :

chroot# apt-get update && apt-get upgrade -y

 

B – Réglage timezone

Première chose à configurer, la timezone.

Dans le chroot :

chroot# ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime

chroot# dpkg-reconfigure --frontend=noninteractive tzdata

 

C – Réglage Locales

Toujours dans le chroot :

chroot# sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen

chroot# sed -i -e 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen

chroot# dpkg-reconfigure --frontend=noninteractive locales

chroot# update-locale LANG=fr_FR.UTF-8

 

D – ACPID

On va installer le paquet acpid, qui va permettre l’extinction et le reboot de la machine depuis l’hyperviseur.

chroot# apt-get install acpid -y

chroot# systemctl enable acpid

Et voila, nos futures VMs auront un bouton power.

 

E – Paquets supplémentaires

Ici, on va rajouter tous les paquets que l’on désire :

chroot# apt-get install ssh htop bash-completion wget man-db dnsutils \

bsd-mailx net-tools whois telnet tcpdump traceroute parted postfix

Liste non exhaustive…

J’évite d’utiliser tasksel pour installer les trucs standards car il a tendance à en mettre trop. Du coup, je le fais à la mimine.

 

F – Copie squelette

On sort du chroot :

chroot# exit

Et on lance la copie de nos fichiers :

# cp skel/etc/* debugo/etc/ -r

 

G – Démontage

Pour être propre :

# umount debugo/{sys,proc,dev/pts,dev,tmp}

# umount /media/cdrom/

 

H – Création de l’archive

On termine en créant notre archive :

# tar zcvf debugo.tar.gz debugo/

Et on peut supprimer le répertoire

# rm debugo/ -r

 

IV – Conclusion

Et voila, on a un tar tout chaud pour nos VMS, et on va voir comment s’en servir pour se créer une VM en quelques secondes.